using System;
using System.Collections;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using SecuBat.Crawling;
using SecuBat.Notification.Whois.ServiceX;
using Css.Diagnostics;
using SecuBat.Logging;

namespace SecuBat.Notification
{
	/// <summary>
	/// Summary description for Class1.
	/// </summary>
	public class DnsQuery
	{
		public static ArrayList GetMailadresses(String domain, bool useServiceX, bool useSmartWhoIs, out String lastCheckedDomain)
		{
			LogManager.Write(TraceLevel.Verbose, "Querying whois services for domain " + domain + ".", "WhoIs");
			ArrayList list = DnsQuery.ExecuteQueries(domain, useServiceX, useSmartWhoIs);

			// Include check for subdomains
			while (list.Count < 1 && domain.Split('.').Length > 2)
			{
				int index = domain.IndexOf('.');
				if (index < domain.Length - 1)
				{
					domain = domain.Substring(index + 1);
					LogManager.Write(TraceLevel.Verbose, "Querying whois services for domain " + domain + ".", "WhoIs");
					list = DnsQuery.ExecuteQueries(domain, useServiceX, useSmartWhoIs);
				}
			}
			
			lastCheckedDomain = domain;
			return list;
		}

		private static ArrayList ExecuteQueries(String domain, bool useServiceX, bool useSmartWhoIs)
		{
			ArrayList list1 = null;
			if (useServiceX && useSmartWhoIs)
			{
				list1 = DnsQuery.QueryServiceX(domain);
				ArrayList list2 = DnsQuery.QuerySmartWhois(domain);
				foreach (String adr in list2)
				{
					if (!list1.Contains(adr))
						list1.Add(adr);
				}
			}
			else if (useServiceX)
			{
				list1 = DnsQuery.QueryServiceX(domain);
			}
			else if (useSmartWhoIs)
			{
				list1 = DnsQuery.QuerySmartWhois(domain);
			}

			DnsQuery.FilterAddresses(list1);

			return list1;
		}

		private static void FilterAddresses(ArrayList list)
		{
			String s = "info@name-space.com";
			if (list.Contains(s))
			{
				list.Remove(s);
			}
		}

		private static ArrayList QueryServiceX(String domain)
		{
			try
			{
				WhoIs whois = new WhoIs();
				String who = whois.GetWhoIS(domain);
				return DnsQuery.ExtractMailAddresses(who);
			}
			catch (Exception ex)
			{
				LogManager.Write(TraceLevel.Error, ex, "DNS Service X Query");
				return new ArrayList();
			}
		}

		private static ArrayList QuerySmartWhois(String domain)
		{
			NameValueCollection param = new NameValueCollection();
			param.Add("pageid", "swhois");
			param.Add("whois", domain);
			String response = DnsQuery.PostForm("http://name.space.xs2.net/cgi-bin/whois.pl", param);
			return DnsQuery.ExtractMailAddresses(response);
		}

		private static ArrayList ExtractMailAddresses(String flowText)
		{
			MatchCollection col = EmailAddressRegex.TheRegex.Matches(flowText);
			ArrayList addresses = new ArrayList(col.Count);
			foreach (Match m in col)
			{
				String adr = m.Value.Replace("\t", "").Replace("\n", "").Trim().ToLower();
				if (!addresses.Contains(adr))
					addresses.Add(adr);
			}

			return addresses;
		}

		private static String PostForm(String actionAddress, NameValueCollection parameters)
		{
			String responseHtml = "";
			try
			{
				string postData = "";
				foreach (String paramKey in parameters.Keys)
				{
					String value = parameters[paramKey];
					if (postData.Length > 0)
						postData += "&";
					postData += paramKey + "=" + HttpUtility.UrlEncode(value);
				}
				HttpWebRequest webRequest = null;
				webRequest = (HttpWebRequest) WebRequest.Create(actionAddress);
				webRequest.Method = "POST";
				webRequest.ContentType = "application/x-www-form-urlencoded";
				byte[] lbPostBuffer = System.Text.Encoding.GetEncoding(1252).GetBytes(postData);
				webRequest.ContentLength = lbPostBuffer.Length;
				webRequest.Timeout = Int32.Parse(ConfigurationSettings.AppSettings["WebRequestTimeout"]);
				webRequest.Credentials = CredentialCache.DefaultCredentials;
				using (Stream loPostData = webRequest.GetRequestStream())
				{
					loPostData.Write(lbPostBuffer,0,lbPostBuffer.Length);
				}

				using (HttpWebResponse loWebResponse = (HttpWebResponse) webRequest.GetResponse())
				{
					Encoding enc = System.Text.Encoding.GetEncoding(1252);
					using (StreamReader loResponseStream = new StreamReader(loWebResponse.GetResponseStream(),enc))
					{
						responseHtml = loResponseStream.ReadToEnd();
					}
				}

			}
			catch (Exception ex)
			{
				LogManager.Write(TraceLevel.Error, ex, "DNS Query Form Posting");
			}

			return responseHtml;
		}
	}
}
